package com.happiness.gateway.utils;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.log.StaticLog;
import com.happiness.base.properties.JwtSecurityProperties;
import io.jsonwebtoken.*;
import io.jsonwebtoken.security.Keys;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.security.Key;
import java.util.*;
import java.util.stream.Collectors;

import static io.jsonwebtoken.impl.TextCodec.BASE64;


/**
 * jwt工具类，实现创建和校验token
 * */
@Component
public class JwtTokenUtils  implements InitializingBean {
    @Resource
    private JwtSecurityProperties jwtSecurityProperties;
    private Key key;

    @Override
    public void afterPropertiesSet() throws Exception {
        byte[] keyBytes = jwtSecurityProperties.getSecret().getBytes();
        this.key = Keys.hmacShaKeyFor(keyBytes);
    }

    /**
     * 根据负责生成JWT的token
     * @param subject 代表这个JWT的主体，即它的所有人 我们采用用户的用户名
     * @param claims 存储在JWT里面的信息 一般放些用户的基本信息：用户昵称、用户名、用户登录平台信息等
     * @return String 返回jwt生成的token
     */
    public String createToken(String subject,Map<String, Object> claims) {
        return Jwts.builder()
                .setIssuer(jwtSecurityProperties.getIssuer())
                .setSubject(subject)
                .setClaims(claims)
                .setExpiration(new Date(System.currentTimeMillis() + jwtSecurityProperties.getExpiration()))
                .compressWith(CompressionCodecs.DEFLATE)
                .signWith(key, SignatureAlgorithm.HS512)
                .compact();
    }

    /**
     * 获取用户名
     * @return       java.lang.String
     */
    public String getUserName(String token){

        String username=null;
        try {
            Claims claims = getClaimsFromToken(token);
            username = claims.getSubject();
        } catch (Exception e) {
            StaticLog.error("error={}",e);
        }
        return username;
    }



    /**
     * 解析token获取登录token信息
     */
    public <T> T getJwtBeanFromToken(String token,Class<T> tClass) {
        Claims claims = getClaimsFromToken(token);
        if (claims==null) return null;
        Collection<? extends GrantedAuthority> authorities =
                Arrays.stream(claims.get(jwtSecurityProperties.getAuth()).toString().split(","))
                        .map(SimpleGrantedAuthority::new)
                        .collect(Collectors.toList());
        return BeanUtil.toBean(claims, tClass);
    }


    /**
     * 获取token过期时间
     * @param token jwt生成的token
     * */
    public Date getExpirationDateFromToken(String token) {
        Date expiration;
        try {
            final Claims claims = getClaimsFromToken(token);
            expiration = claims.getExpiration();
        } catch (Exception e) {
            expiration = null;
        }
        return expiration;
    }

    public boolean validateToken(String authToken) {
        try {
            Jwts.parserBuilder().setSigningKey(key).build().parseClaimsJws(authToken);
            return true;
        } catch (SecurityException | MalformedJwtException e) {
            StaticLog.info("Invalid JWT signature.");
        } catch (ExpiredJwtException e) {
            StaticLog.info("Expired JWT token.");
        } catch (UnsupportedJwtException e) {
            StaticLog.info("Unsupported JWT token.");
        } catch (IllegalArgumentException e) {
            StaticLog.info("JWT token compact of handler are invalid.");
        }
        return false;
    }

    private Claims  getClaimsFromToken(String token) {
        Claims claims;
        try {
            claims = Jwts.parserBuilder()
                    .setSigningKey(key)
                    .build()
                    .parseClaimsJws(token)
                    .getBody();
        } catch (Exception e) {
            claims = null;
        }
        return claims;
    }
}
